package com.utilities.fastaUtilities;

import java.io.BufferedReader;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.TreeSet;

import com.utilities.IO.FileUtilities;
import com.utilities.dataStructures.Range;
import com.utilities.parsers.coordsParser.ParseCoordsFileParser;
import com.utilities.pipelineScripts.RangeComparator;

public class MummerUtilities {


	/**
	 * params[0] : contigs file containing names of contigs to be fetched
	 * params[1] : nucmer.delta file
	 * params[2] : output Delta file to be created
	 * @param args
	 */
	public void filterNucmerFile(String[] args)
	{
		try
		{
			ArrayList<String> list = new ArrayList<String>();
			BufferedReader bufferedReader = new BufferedReader(new FileReader(args[0]));
			String readLine = bufferedReader.readLine();
			while(readLine != null)
			{
				list.add(readLine.trim());
				readLine = bufferedReader.readLine();
			} 
			bufferedReader.close();
			FileWriter fw = new FileWriter(args[2]);
			bufferedReader = new BufferedReader(new FileReader(args[1]));
			readLine = bufferedReader.readLine();
			boolean append = false;
			System.out.println(list.size());
			while(readLine != null)
			{
				if (readLine.startsWith(">"))
				{
					append = false;
					boolean contains = false;
					for (String contig : list)
					{
						if (readLine.contains(contig))
						{
							fw.write(readLine.trim() + "\n");
							//							System.out.println(contig + " here");
							contains = true;
							break;
						}
					}
					if (contains)
					{
						append = true;
					}
				}
				else if (append)
				{
					fw.write(readLine + "\n");
				}
				readLine = bufferedReader.readLine();
			}
			fw.flush();
			fw.close();
			bufferedReader.close();
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}


	/**
	 * args[0] : show tilings tab delimited output file
	 * args[1] : output file
	 * @param args
	 */
	public void fetchContigsFromShowTiling(String[] args)
	{
		try
		{
			FileWriter fileWriter = new FileWriter(new File(args[1]));
			BufferedReader bufferedReader = new BufferedReader(new FileReader(args[0]));
			String readLine = bufferedReader.readLine();
			while(readLine != null)
			{
				if (readLine.startsWith(">"))
				{
				}
				else
				{
					String[] params = readLine.split("\t");
					fileWriter.write(params[7] + "\n");
				}
				readLine = bufferedReader.readLine();
			}
			bufferedReader.close();
			fileWriter.close();
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * args[0] : paths of the file containing all the contigs
	 * args[1] : path of the file containing ordered contigs (tiling file)
	 * @param args
	 * returns a list containing list of allContigs, tiledcontigs and notTiled contigs in that order
	 */
	public ArrayList<ArrayList<String>> fetchContigsFoundAndNotFound(String[] args)
	{
		ArrayList<String> allContigs = OtherUtilities.getSequenceNames(args[0]); 
		ArrayList<String> contigsFromTiling = getTilingContigs(args[1]);
		ArrayList<String> contigsNotTiled = new ArrayList<String>();
		for(String contig : allContigs)
		{
			if (!contigsFromTiling.contains(contig))
			{
				contigsNotTiled.add(contig);
			}
		}

		ArrayList<ArrayList<String>> lists = new ArrayList<ArrayList<String>>();
		lists.add(allContigs); lists.add(contigsFromTiling);lists.add(contigsNotTiled);
		return lists;
	}


	public static ArrayList<String> getTilingContigs(String file) {
		ArrayList<String> lst = new ArrayList<String>();
		try
		{
			BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
			String readLine = bufferedReader.readLine();
			while(readLine != null)
			{
				if (!readLine.startsWith(">"))
				{
					String[] params = readLine.split("\t");
					lst.add(params[7].trim());
				}
				readLine = bufferedReader.readLine();
			}
			bufferedReader.close();
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return lst;
	}

	/**
	 * @param args
	 * args[0] : tiling file
	 * args[1] : coords file
	 * args[2] : all contigs file
	 * args[3] : reference Seq Size
	 * @return
	 */
	public ArrayList<ArrayList<Range>> getIncludedExcludedAndNotAlignedContigRanges(String[] args)
	throws Exception
	{
		ArrayList<ArrayList<Range>> result = new ArrayList<ArrayList<Range>>();
		ArrayList<Range> excluded = new ArrayList<Range>();
		ArrayList<Range> contigsNotAligned = new ArrayList<Range>();
		ArrayList<String> allContigs = OtherUtilities.getSequenceNames(args[2]);
		
		ArrayList<String> contigsFromTiling = getTilingContigs(args[0]);
		int refSeqSize = Integer.parseInt(args[3]);
		
//		TreeSet<String> temp_list = new TreeSet<String>(allContigs);
		BufferedReader bufferedReader = new BufferedReader(new FileReader(args[1]));
		String readLine = bufferedReader.readLine();
		ParseCoordsFileParser allContigsFileParser = new ParseCoordsFileParser();
		while(readLine != null)
		{
			String[] params = allContigsFileParser.parseCoordsFileLine(readLine);
			if (!contigsFromTiling.contains(params[14].trim()))
			{
				int start = Integer.parseInt(params[0].trim());
				int end  = Integer.parseInt(params[1].trim());
				if (start > end)
				{
					int temp = start; start = end ; end = temp;
				}
				if (start < 0)
				{
					start = refSeqSize + start;
					System.out.println("negative for \n params[14]");
				}
				Range range = new Range(start, end, readLine.trim());
				excluded.add(range);
//				temp_list.remove(params[14].trim());
			}
			allContigs.remove(params[14].trim());
			readLine = bufferedReader.readLine();
		}
		bufferedReader.close();
		for (String contig : allContigs)
		{
			Range range = new Range(0, 0, contig);
			contigsNotAligned.add(range);
		}
		result.add(excluded);
		result.add(contigsNotAligned);
		return result;
	}


	public static ArrayList<ArrayList<String>> getTiledAndExcludedContigs(
			String tilingFile, String coordsFile) throws IOException {
		ArrayList<ArrayList<String>> result = new ArrayList<ArrayList<String>>();
		ArrayList<String> tiledList = getTilingContigs(tilingFile);
		result.add(tiledList);
		ArrayList<String> excludedList = new ArrayList<String>();
		
		TreeSet<String> set = new TreeSet<String>();
		BufferedReader bufferedReader = new BufferedReader(new FileReader(coordsFile));
		String readLine = bufferedReader.readLine();
		ParseCoordsFileParser allContigsFileParser = new ParseCoordsFileParser();
		while(readLine != null)
		{
			String[] params = allContigsFileParser.parseCoordsFileLine(readLine);
			if (!tiledList.contains(params[14].trim()))
			{
				set.add(params[14].trim());
			}
			readLine = bufferedReader.readLine();
		}	
		excludedList.addAll(set);
		result.add(excludedList);
		return result;
	}
	
	public static ArrayList<Range> getGaps(String tilingFile) throws Exception
	{
		ArrayList<Range> gapList = new ArrayList<Range>();
		ArrayList<Range> contigList = new ArrayList<Range>();
		BufferedReader bufferedReader = new BufferedReader(new FileReader(tilingFile));
		String readLine = bufferedReader.readLine();
		while(readLine != null)
		{
			if (!readLine.startsWith(">"))
			{
				String[] params = readLine.split("\t");
				int start = Integer.parseInt(params[0]);
				int end = Integer.parseInt(params[1]);
				Range range = new Range(start, end, readLine);
				contigList.add(range);
			}
			readLine = bufferedReader.readLine();
		}	
		bufferedReader.close();
		ArrayList<Range> contigs_ = new ArrayList<Range>();
		Collections.sort(contigList,new RangeComparator());
		int current = 1;
		for (Range contig : contigList)
		{
			int start = contig.getLowerLimit();
			if (current < start)
			{
				Range gap = new Range(current, start - 1, contig.getMetadata());
				gapList.add(gap);
			}
			current = contig.getUpperLimit() +1;
		}
		return gapList;
	}
	
//	public ArrayList<ArrayList<Range>> filterTilingFile(int seqLength, String tilingFile, 
//			String gapsFile, String contigsFile) throws IOException
//			{
//		ArrayList<ArrayList<Range>> result = new ArrayList<ArrayList<Range>>();
//		ArrayList<Range> gapList = new ArrayList<Range>();
//		ArrayList<Range> contigs = new ArrayList<Range>();
//
//		// start reading the tiling file
//		BufferedReader bufferedReader = new BufferedReader(new FileReader(tilingFile));
//		String readLine = bufferedReader.readLine();
//		int current = 1;
//		int overlapping = 1;
//		while(readLine != null)
//		{
//			if (!readLine.startsWith(">"))
//			{
//				String[] params = readLine.split("\t");
//				int start = Integer.parseInt(params[0]);
//				int end = Integer.parseInt(params[1]);
//				double alignmentCov =  Double.parseDouble(params[5]);
//				double actualLength = (alignmentCov * Integer.parseInt(params[3].trim()))/100;
//				Range contig = new Range(start, end, params[7].trim(),Integer.parseInt(params[3].trim())).setActualLength((double)Math.round(actualLength));
//				contigs.add(contig);
//				if (current < start)
//				{
//					Range range = new Range(current, start - 1, params[7].trim());
//					gapList.add(range);
//					current = end + 1;
//				}
//				else if (current >= start && current < end)
//				{
//					overlapping++;
//					current = end + 1;
//				}
//				else if (current > end)
//				{
//
//				}
//			}
//			readLine = bufferedReader.readLine();
//		}
//		if (current < seqLength) 
//		{
//			int ultimateStarter = contigs.get(0).getLowerLimit();
//			int diff = 0;
//			if (ultimateStarter < 0)
//			{
//				diff = ultimateStarter  - 1;
//			}
//			Range range = new Range(current, seqLength + diff, "trailing");
//			gapList.add(range);
//		}
//		result.add(contigs); result.add(gapList);
//		return result;
//			}
}
